package com.apobates.jforum2.troll.replies;

import com.apobates.jforum2.troll.regular.ActionDescriptor;
import com.apobates.jforum2.troll.replies.biz.PostsService;
import com.apobates.jforum2.troll.replies.biz.impl.api.PostsActionLogStreamProvider;
import com.apobates.jforum2.troll.replies.entity.Posts;
import com.apobates.jforum2.troll.utils.core.api.ActionEventCulpritor;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.CodeSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import java.util.Optional;

@Configuration
@Aspect
public class PostsActionLogAspect {
    @Autowired
    private PostsService postsService;
    @Autowired
    private PostsActionLogStreamProvider postsActionLogStreamProvider;
    private final static Logger logger = LoggerFactory.getLogger(PostsActionLogAspect.class);

    @Before("execution(* com.apobates.jforum2.troll.replies.biz.impl.*.*(..)) && @annotation(actionDescriptor) && args(.., culpritor)")
    public void enjoy(JoinPoint joinPoint, ActionEventCulpritor culpritor, ActionDescriptor actionDescriptor){
        logger.info("[CAT]12>1 method start");
    }
    //目前有:POSTS_DEL,POSTS_EDIT;POSTS_LIKED,
    @AfterReturning(
            pointcut="@annotation(actionDescriptor) && args(.., culpritor)",
            returning="retVal")
    public void check(
            JoinPoint joinPoint,
            ActionEventCulpritor culpritor,
            ActionDescriptor actionDescriptor,
            Object retVal) throws Throwable{
        //方法名
        String methodName = joinPoint.getSignature().toShortString(); //TopicServiceImpl.browse(..)
        logger.error("[CAT][Posts]12>3 methodName: "+methodName);
        String[] classNameMethodName = methodName.replace("(..)", "").split("\\.");
        if(classNameMethodName == null || classNameMethodName.length != 2) {
            return;
        }
        //主键
        Long primaryKey = null;
        Optional<Posts> posts = Optional.empty();
        if(!actionDescriptor.isBool()) {
            if(retVal instanceof Posts) {
                posts = Optional.ofNullable((Posts)retVal);
            }else{
                primaryKey = Long.valueOf(retVal.toString());
            }
        }else {
            CodeSignature signature=(CodeSignature)joinPoint.getStaticPart().getSignature();
            try {
                primaryKey = getPrimaryKey(joinPoint.getArgs(), signature.getParameterNames(), actionDescriptor.keyName());
            }catch (Exception e){
                if(logger.isDebugEnabled()){
                    logger.debug(e.getMessage(), e);
                }
                logger.error("[CAT][Posts]12>3.1 get primary key error: exception:"+e.getMessage());
            }
        }
        //
        if(null!=primaryKey && primaryKey.compareTo(0L)==1) {
            posts = postsService.get(primaryKey);
        }
        if(posts.isPresent()) {
            logger.error("[CAT][Posts]12>4 publish event action ");
            postsActionLogStreamProvider.action(actionDescriptor.action(), posts.get(), culpritor);
        }else {
            logger.error("[CAT][Posts]12>5 query entity by primary key fail");
        }
    }

    private Long getPrimaryKey(Object[] paramValues, String[] paramNames, String keyName) {
        Long key = -1L;
        for(int i=0;i<paramValues.length;i++){
            if(!"null".equalsIgnoreCase(keyName) && keyName.equals(paramNames[i])){
                try {
                    key = (Long)paramValues[i];
                }catch(ClassCastException e) {
                    logger.error("[CAT][Posts]12>3.1 loop primary key fail, err: "+e.getMessage());
                    key = 0L;
                }
            }
        }
        return key;
    }
}
